
	MROS - Midi Realtime Operating System
	
	Interfacing to MROS Midi i/o for simple Applictions which
	don't use the Time Manager and Midi Multitasking...

	... can be done via MROS without having to license to MROS.
	This document is related to the ATARI version. Note that
	Steinberg provides this information without any warranty.
	Along with this text you should find mrmidi.c, mrasm.s,
	and mrmidi.prj (Pure-C project file) for a small test
	program using all MROS functions explained here.

	First of all, load and execute MROS (you may rename
	MROSx_xx to MROSx_xx.PRG and start it from the desktop).
	Then register your application to the MEM (Message Manager):

/*-----------------------------------------------------------------*/

#define Open_mros(a)        MEM(0,a)
#define Close_mros(a)       MEM(1,a)

LONG MEM(void,...);

typedef struct mem_struct
{
   VOID *a;
   WORD b;
   WORD c;
   WORD d;  
   WORD e;
   WORD f; 
   WORD g;
   WORD h;
   BYTE i[14];
   BYTE appl_name[16];	/* write name in here       */  
} MEM_STRUCT;

MEM_STRUCT my_mros;
WORD mroshandle = 0;

VOID start_mros(VOID)
{
	if(mroshandle > 0) return;
	memset(&my_mros, 0, sizeof(MEM_STRUCT));
	strcpy(my_mros.appl_name, "My Application");	/* max 15 char */
	mroshandle = (WORD)Open_mros(&my_mros);
}

/*	... and at the end of Your application, don't forget to */

VOID end_mros(VOID)
{
	if(mroshandle <= 0) return;
	Close_mros(mroshandle);
	mroshandle = 0;
}

/*-----------------------------------------------------------------*/

	Midi I/O is handled by the IOM (Input Output Manager).
	There are two ways to access data from any one Midi Input.
	The one described here has no multitasking capabilities,
	but is sufficient as long as only one application uses
	it, thus you can use it without interfering Cubase:

#define Mget(a,b)               IOM(5,a,b)

LONG IOM(void,...);

WORD Mget(WORD device, WORD input);

	returns a negative number if no Byte is available on this
	input, otherwise the next Midi Byte. See below how to find
	out which devices are connected.

	Two functions are available to output midi data:

#define Snd_mevent(a,b,c,d,e)   IOM(2,a,b,c,d,e)
#define Snd_mmult(a,b,c,d)      IOM(3,a,b,c,d)

WORD Snd_mevent(WORD device, WORD output,
	WORD byte1, WORD byte2, WORD byte3);

	which is mainly used for Channel Events. For 2 Byte Events
	(like Program Change), set byte3 to -1. You might also
	use the following function, which is intented to be used
	for sysex-dumps:

WORD Snd_mmult(WORD device, WORD output,
	BYTE *data, UWORD size);

	Of course, you will need to know which MROS Midi Devices
	are active. Use this:

#define Next_device(a,b)        IOM(22,a,b)

DEV_STRUCT *Next_device(WORD type, WORD first_flag);

	Set type to zero (Midi Type). Set 'first_flag' to non-zero
	for the first call, and to zero for subsequent calls.
	Repeat calling this function until it returns a negative
	number. Else it will return a pointer to the device's
	definition structure:

typedef struct dev_struct
{
	VOID *a;
	WORD b;
	WORD c;
	WORD d;
	WORD e;
	VOID *f;
	VOID *g;
	VOID *h;
	VOID *i;
	WORD devact;				/* <>0, if device active            */
	WORD devnum;				/* device no.                       */
	WORD devmins;				/* no. of midi inputs (0=no input)  */
	WORD devmouts;				/* midi outputs                     */
	VOID *j;
	VOID *k;
	VOID *l;
	WORD m;
	WORD n;
	WORD o;
	WORD devvers;				/* version no.						*/
	BYTE devname[8];			/* 8 ascii device name              */
} DEV_STRUCT;

	In this way you can build a list of Inputs and Outputs, using
	the device name and the number of Inputs/Outputs.

	Finally, here's how to access the MEM and the IOM:

MEM:
	move.l	(sp)+,savmemp		; save caller's return address
	trap	#8					; call trap
	move.l	savmemp(pc),-(sp)	; restore return address
	rts
savmemp:
	dc.l	0

IOM:
	move.l	(sp)+,saviomp
	trap	#10
	move.l	saviomp(pc),-(sp)
	rts
saviomp:
	dc.l	0

